package com.yuanian.timingwheel.threadpool;

import com.yuanian.timingwheel.context.ExecutionContext;
import com.yuanian.timingwheel.model.task.TaskStatus;
import com.yuanian.timingwheel.model.task.base.BaseTask;
import java.util.concurrent.*;

/**
 * 线程池使用门面类
 */
public class ThreadPoolExecutorFacade {

    private static ThreadPoolExecutorFacade instance = new ThreadPoolExecutorFacade();

    private ThreadPoolExecutorFacade() {

    }

    //队列
    private LinkedBlockingQueue queue = new LinkedBlockingQueue<>(10000000);

    private ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors() + 1,
            Runtime.getRuntime().availableProcessors() + 1,
            10,
            TimeUnit.SECONDS,
            queue,
            (runnable) -> {
                Thread thread = new Thread(runnable);
                thread.setName("tw时间轮线程");
                return thread;
            },
            new ThreadPoolExecutor.DiscardPolicy()
    );

    public void clearQueue() {
        queue.clear();
    }

    public LinkedBlockingQueue getQueue() {
        return queue;
    }

    /**
     * 是否还有没有运行的任务
     * @return
     */
    public boolean isCompleted() {
        return queue.isEmpty() && ExecutionContext.getInstance().getLivingServer().isCompleted();
    }

    /**
     * 执行任务
     * @param task
     */
    public void execute(BaseTask task) {
        //此行代码必须放在外面，不然引起并发问题
        ExecutionContext.getInstance().getLivingServer().getWaitingTasks().put(task.getId(), task);
        task.setTaskStatus(TaskStatus.WAITING);
        threadPoolExecutor.execute(() -> {
            try {
                ExecutionContext.getInstance().getLivingServer().getWaitingTasks().remove(task.getId());
                ExecutionContext.getInstance().getLivingServer().getRunningTasks().put(task.getId(), task);
                task.setTaskStatus(TaskStatus.RUNNING);
                task.execute();
            }  finally {
                ExecutionContext.getInstance().getLivingServer().getRunningTasks().remove(task.getId());
                ExecutionContext.getInstance().getLivingServer().getHandledTasks().put(task.getId(), task);
                task.setTaskStatus(TaskStatus.HANDLED);
            }
        });
    }

    public static ThreadPoolExecutorFacade getInstance() {
        return instance;
    }

}
